﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.Text;

namespace JupiterLibrary
{
    public class InputEngine
    {
        /// <summary>
        /// Indica que es la 1ª vez que se entra en el Input
        /// </summary>
        bool firstTime = true;
        public bool isKinect { get; set; }
        /// <summary>
        /// State del teclado en el frame anterior
        /// </summary>
        KeyboardState lastKeyboardState;

        public KeyboardState KeyState;

        /// <summary>
        /// State del ratón en este frame
        /// </summary>
        MouseState mouseState;

        /// <summary>
        /// state del ratón en el frame anterior
        /// </summary>
        MouseState lastMouseState;

        public bool UseMouseInput = true;

        /// <summary>
        /// Devuelve el incremento de desplazamiento del ratón en el eje X
        /// </summary>
        public int MouseRelativeX
        {
            get;
            private set;
        }

        /// <summary>
        /// Devuelve el incremento de desplazamiento del ratón en el eje X
        /// </summary>
        public int MouseRelativeY
        {
            get;
            private set;
        }

        public Point MousePosition;

        Point lastPosition;

        GameTime gameTime;

        public InputEngine()
        {
        }

        public void Update()
        {
            int viewPortWidth=Jupiter.Video.GraphicsDevice.Viewport.Width;
            int viewPortHeight=Jupiter.Video.GraphicsDevice.Viewport.Height;

            this.gameTime = Jupiter.GameTime;

            lastKeyboardState = KeyState;

            KeyState = Keyboard.GetState();

            if (!UseMouseInput) return;

            lastMouseState = mouseState;

            mouseState = Mouse.GetState();

            int centerX = viewPortWidth / 2;
            int centerY = viewPortHeight / 2;

            if (firstTime)
            {
                MouseRelativeX = MouseRelativeY = 0;

                lastPosition.X = mouseState.X;
                lastPosition.Y = mouseState.Y;

                firstTime = false;

            }
            else
            {
                MouseRelativeX = mouseState.X - lastPosition.X;
                MouseRelativeY = mouseState.Y - lastPosition.Y;

            }

            // Calculo la posición del ratón absoluta
            MousePosition.X += MouseRelativeX;
            MousePosition.Y += MouseRelativeY;

            if (MousePosition.X < 0) MousePosition.X = 0;
            if (MousePosition.Y < 0) MousePosition.Y = 0;

            if (MousePosition.X > viewPortWidth) MousePosition.X = viewPortWidth - 1;
            if (MousePosition.Y > viewPortHeight) MousePosition.Y = viewPortHeight - 1;

            lastPosition = MousePosition;

            // Dejo el ratón en el centro, porque yo sólo utilizo el desplazamiento relativo
            // Si no lo hago cuando el ratón llega abajo, ya no baja más!!
            //if (!isKinect)
            //{
            //    Mouse.SetPosition(centerX, centerY);
            //}
            lastPosition = new Point(centerX, centerY);
        }

        public bool SalirDelJuego()
        {
            return KeyState.IsKeyDown(Keys.Escape);
        }

        public bool ClickSobreRectangulo(Rectangle rect)
        {
            // Aquí deberemos comparar con todos los posibles puntos de 'toque' del multitouch

            if (IsLeftMouseButtonClickedAndReleased())
            {
                if (rect.Contains(MousePosition))
                    return true;
            }
            return false;
        }

        #region LowLevel

        /// <summary>
        /// Comprueba si se ha hecho click en la tecla
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool IsKeyClicked(Keys key)
        {
            if (key == Keys.LeftWindows) return IsLeftMouseButtonClicked();
            if (key == Keys.RightWindows) return IsRightMouseButtonClicked();

            return KeyState.IsKeyDown(key) && lastKeyboardState.IsKeyUp(key);
        }

        /// <summary>
        /// Comprueba si el botón izquierdo del ratón está pulsado
        /// </summary>
        /// <returns></returns>
        public bool IsLeftMouseButtonPressed()
        {
            return (mouseState.LeftButton == ButtonState.Pressed);
        }

        public bool IsLeftMouseButtonPressed(Rectangle rect)
        {
            return (rect.Contains(MousePosition) && IsLeftMouseButtonPressed());
        }


        /// <summary>
        /// Comprueba si el botón derecho del ratón está pulsado
        /// </summary>
        /// <returns></returns>
        public bool IsRightMouseButtonPressed()
        {
            return (mouseState.RightButton == ButtonState.Pressed);
        }

        /// <summary>
        /// Comprueba si se ha hecho un 'click' con el botón izquierdo del ratón
        /// </summary>
        /// <returns></returns>
        public bool IsLeftMouseButtonClicked()
        {
            return (mouseState.LeftButton == ButtonState.Pressed && lastMouseState.LeftButton == ButtonState.Released);
        }

        /// <summary>
        /// Comprueba si se ha hecho un 'click' con el botón izquierdo del ratón y el estado del ratón es 'soltado'
        /// </summary>
        /// <returns></returns>
        public bool IsLeftMouseButtonClickedAndReleased()
        {
            return (mouseState.LeftButton == ButtonState.Released && lastMouseState.LeftButton == ButtonState.Pressed);
        }

        /// <summary>
        /// Comprueba si se ha hecho un 'click' con el botón derecho del ratón
        /// </summary>
        /// <returns></returns>
        public bool IsRightMouseButtonClicked()
        {
            return (mouseState.RightButton == ButtonState.Pressed && lastMouseState.RightButton == ButtonState.Released);
        }

        /// <summary>
        /// Devuelve True si la tecla shift izquierda o derecha está pulsada
        /// </summary>
        /// <returns></returns>
        public bool IsShiftPressed()
        {
            return (IsKeyPressed(Keys.LeftShift) || IsKeyPressed(Keys.RightShift));
        }

        /// <summary>
        /// Comprueba si la tecla está pulsada
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool IsKeyPressed(Keys key)
        {
            // Para compatibilizar código, se asumen ciertas teclas que simulan el ratón
            if (key == Keys.LeftWindows) return IsLeftMouseButtonPressed();
            if (key == Keys.RightWindows) return IsRightMouseButtonPressed();

            return KeyState.IsKeyDown(key);
        }

        #endregion

    }
}
